/*!
 * \file jboss_core.c
 *
 * \brief jboss数据包解析
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.\n
 *
 * \version 2.0
 * \author geyh
 * \date 2015/11/05
 *
 */
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>

#include "frservice_comm.h"
#include "frmem.h"
#include "frcomm.h"
#include "frhash2.h"
#include "frct_comm.h"
#include "config.h"
#include "jbossmq_comm.h"
#include "jbossmq_core.h"

extern void *g_p_apm_context;
/*!
 * 私有数据创建
 *
 * \
 * \return APM_L7_IS_NO:不属于TCP协议\n
 *         APM_L7_IS_YES:属于TCP协议
 *
 */
FR_STATIC L7session_jboss_private* __jboss_private_create(void)
{
    L7session_jboss_private *p_st_private = NULL;

    p_st_private = (L7session_jboss_private*)frmalloc(sizeof(L7session_jboss_private));
    if(p_st_private == NULL)
        return NULL;

    memset(p_st_private, '\0', sizeof(L7session_jboss_private));

    p_st_private->p_st_data = bytebuff_creat();
    if(p_st_private->p_st_data == NULL)
    {
        frfree(p_st_private);
        return NULL;
    }

    return p_st_private;
}

FR_STATIC int __jboss_session_reset(L7session_jboss_private *p_st_private)
{
    if(p_st_private == NULL)
        return FR_FAIL;

    if(p_st_private->p_st_body_data_req)
        frreport_body_free(&p_st_private->p_st_body_data_req);
    if(p_st_private->p_st_body_data_resp)
        frreport_body_free(&p_st_private->p_st_body_data_resp);

    if(p_st_private->p_lst_req_tmp)
        frreport_body_l7list_free(&p_st_private->p_lst_req_tmp);

    if(p_st_private->p_lst_comm_tmp)
        frreport_body_l7list_free(&p_st_private->p_lst_comm_tmp);

    if(p_st_private->p_lst_mq_tmp)
        frreport_body_l7list_free(&p_st_private->p_lst_mq_tmp);

    if(p_st_private->p_st_data)
        bytebuff_free(&p_st_private->p_st_data);

    p_st_private->p_st_data = bytebuff_creat();
    if(p_st_private->p_st_data == NULL)
        return FR_FAIL;

    p_st_private->is_topic = 0;
    p_st_private->is_message = 0;
    p_st_private->i_flag_report = 0;
    p_st_private->i_flag_data_type = 0;
    p_st_private->i_data_len = 0;

    memset(&p_st_private->st_l4_trans, '\0', sizeof(L4_transaction));
    return FR_SUCC;
}


FR_STATIC int __jboss_session_report(Frreport_body_data *p_st_body_data, L7session_jboss_private *p_st_private)
{
    char arr_tmp[1024];
    int i_ret = 0;

    if(p_st_body_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    if(p_st_private->st_login_timestamp.tv_sec)
    {
        if(p_st_private->p_user_name)
        {
            if(frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_SESSION_USERNAME, p_st_private->p_user_name) == FR_FAIL)
                return FR_FAIL;
        }
        else
        {
            if(frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_SESSION_USERNAME, "\0") == FR_FAIL)
                return FR_FAIL;
        }
        if(frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_SESSION_ID, p_st_private->arr_session_id) == FR_FAIL)
            return FR_FAIL;

        if(frreport_body_l7_add_timeval(p_st_body_data, APM_REPORT_KEY_SESSION_LOGIN_TIMESTAMP, &p_st_private->st_login_timestamp) == FR_FAIL)
            return FR_FAIL;
    }


    if(p_st_private->p_title)
    {

        if(p_st_private->is_topic)
        {
            i_ret = frreport_body_l7_add_str(p_st_body_data, "session.mq.topic", p_st_private->p_title);
            if(i_ret == FR_FAIL)
                return FR_FAIL;
        }
        else
        {
            i_ret = frreport_body_l7_add_str(p_st_body_data, "session.mq.queue", p_st_private->p_title);
            if(i_ret == FR_FAIL)
                return FR_FAIL;
        }

        if(p_st_private->i_use_request)
        {
            if(p_st_private->is_message)
                snprintf(arr_tmp, sizeof(arr_tmp), "PUT %s", p_st_private->p_title);
            else
                snprintf(arr_tmp, sizeof(arr_tmp), "SUB %s", p_st_private->p_title);
        }
        else
        {
            snprintf(arr_tmp, sizeof(arr_tmp), "NOTIFY %s", p_st_private->p_title);
        }

        i_ret = frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_TRANS_TITLE, arr_tmp);
        if(i_ret == FR_FAIL)
            return FR_FAIL;

    }
    else
    {
        if(p_st_private->i_use_request)
        {
            if(p_st_private->is_message)
                i_ret = frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_TRANS_TITLE, "PUT");
            else
                i_ret = frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_TRANS_TITLE, "SUB");
        }
        else
            i_ret = frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_TRANS_TITLE, "NOTIFY");
        if(i_ret ==FR_FAIL)
            return FR_FAIL;
    }

    return FR_SUCC;
}



/*!
 * 判断是否为JBOSS数据包
 *
 * \param *p_st_conn       (Conntrack      连接信息)
 * \param *p_st_packet    (Apm_packet    数据包信息)
 *
 * \return APM_L7_IS_NO:不属于TCP协议\n
 *         APM_L7_IS_YES:属于TCP协议
 *
 */
int jboss_detect(Conntrack *p_st_conn, Apm_packet *p_st_packet)
{
    int i_ret = 0;
    char *p_data = NULL;
    int i_data_len = 0, i_data_len_tmp = 0, i_direction = FR_DIRECT_UNKNOWN;
    unsigned char uc_type;
    Frbyte_Packet *p_packet = NULL;
    L7session_jboss_private *p_st_private = NULL;

    if(p_st_conn == NULL || p_st_packet == NULL || p_st_packet->p_payload == NULL || p_st_packet->ui_payload_len == 0)
        return APM_L7_IS_NO;

    p_st_private = __jboss_private_create ();
    if(p_st_private == NULL)
        return APM_L7_IS_NO;

    //四位数据长度  不包含本身
    p_data = p_st_packet->p_payload;
    i_data_len = p_st_packet->ui_payload_len;

    if(i_data_len < 4)
        goto FAIL;
    i_data_len_tmp = pntohi(p_data);

    i_data_len -= 4;
    p_data += 4;

    if(i_data_len != i_data_len_tmp)
        goto FAIL;

    //获取数据类型
    if(i_data_len < 1)
        goto FAIL;

    uc_type = (unsigned char)*p_data;

    p_data++;
    i_data_len--;

    switch(uc_type)
    {
        case 0x0a:
            if(i_data_len != 16)
                goto FAIL;

            p_data += 14;
            if(memcmp(p_data, "\xea\x60", 2) != 0)
                goto FAIL;

            break;

        case 0x71:
            if(i_data_len != 13)
                goto FAIL;

            p_data += 12;
            if(memcmp(p_data, "\x7a", 1) != 0)
                goto FAIL;
            break;

        case 0x1e:
            p_packet = bytebuff_creat();
            if(p_packet == NULL)
                goto FAIL;

            bytebuff_add(p_packet, p_data, i_data_len);

            i_ret = jboss_connection_parse(p_packet, p_st_private, FR_NO);
            bytebuff_free(&p_packet);
            if(i_ret == FR_FAIL)
                goto FAIL;

            i_direction = FR_DIRECT_CLIENT2SRV;
            break;

        case 0x22:
            p_packet = bytebuff_creat();
            if(p_packet == NULL)
                goto FAIL;

            bytebuff_add(p_packet, p_data, i_data_len);

            i_ret = jboss_sub_parse(p_packet, NULL, p_st_private, FR_NO);
            bytebuff_free(&p_packet);
            if(i_ret == FR_FAIL)
                goto FAIL;

            i_direction = FR_DIRECT_CLIENT2SRV;
            break;

        case 0x47:
            p_packet = bytebuff_creat();
            if(p_packet == NULL)
                goto FAIL;

            bytebuff_add(p_packet, p_data, i_data_len);

            i_ret = jboss_message_parse(p_packet, NULL, p_st_private, FR_NO);
            bytebuff_free(&p_packet);
            if(i_ret == FR_FAIL)
                goto FAIL;

            i_direction = FR_DIRECT_CLIENT2SRV;
            break;

        case 0x4b:

            p_packet = bytebuff_creat();
            if(p_packet == NULL)
                goto FAIL;

            bytebuff_add(p_packet, p_data, i_data_len);

            i_ret = jboss_message_parse(p_packet, NULL, p_st_private, FR_NO);
            bytebuff_free(&p_packet);
            if(i_ret == FR_FAIL)
                goto FAIL;

            i_direction = FR_DIRECT_SRV2CLIENT;
            break;

        default:
            goto FAIL;
    }

    //方向判断  方向确定 直接返回
    i_ret = frct_get_direct_known(p_st_conn);
    if(i_ret == FR_DIRECT_KNOWN)
    {
        if(p_st_packet->i_direction == FR_DIRECT_CLIENT2SRV)
            frservice_add(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0);
        else
            frservice_add(g_p_apm_context, MODULE_L7PROTO, p_st_packet->src_ip, p_st_packet->src_port, NULL, 0);

        goto SUCC;
    }

    if(i_direction == FR_DIRECT_CLIENT2SRV)
    {
        frcap_set_cs_srv(p_st_conn, p_st_packet->dst_ip, p_st_packet->dst_port);
        frservice_add(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0);
        goto SUCC;
    }
    else if(i_direction == FR_DIRECT_SRV2CLIENT)
    {
        frcap_set_cs_srv(p_st_conn, p_st_packet->src_ip, p_st_packet->src_port);
        frservice_add(g_p_apm_context, MODULE_L7PROTO, p_st_packet->src_ip, p_st_packet->src_port, NULL, 0);
        goto SUCC;
    }

    i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0, NULL);
    if (i_ret == FR_SUCC)
    {
        if (frct_get_direct_known(p_st_conn) == FR_DIRECT_UNKNOWN)
            frcap_set_cs_srv(p_st_conn, p_st_packet->dst_ip, p_st_packet->dst_port);

        goto SUCC;
    }

    i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->src_ip, p_st_packet->src_port, NULL, 0, NULL);
    if (i_ret == FR_SUCC)
    {
        if (frct_get_direct_known(p_st_conn) == FR_DIRECT_UNKNOWN)
            frcap_set_cs_srv(p_st_conn, p_st_packet->src_ip, p_st_packet->src_port);
        goto SUCC;
    }

FAIL:
    if(p_st_private)
        jboss_session_destroy (p_st_private);

    return APM_L7_IS_NO;

SUCC:
    if(p_st_private)
        jboss_session_destroy (p_st_private);

    return APM_L7_IS_YES;
}

/*!
 * jboss 数据过滤
 *
 * \param *p_data_in        (char          输入数据)
 * \param i_data_len        (int           输入数据长度)
 * \param *p_st_private     (L7session_jboss_private      私有数据)
 *
 */
FR_STATIC void __jboss_data_filter(char *p_data_in, int i_data_len, L7session_jboss_private *p_st_private)
{
    if(p_data_in == NULL || i_data_len < 5 || p_st_private == NULL)
        return;

    if(*(p_data_in + 4) == '\x22' || *(p_data_in + 4) == '\x47' || *(p_data_in + 4) == '\x4b' )
    {
        p_st_private->i_flag_report = 1;
    }

    return;
}

/*!
 * jboss 数据过滤
 *
 * \param *p_data_in        (char          输入数据)
 * \param i_data_len        (int           输入数据长度)
 * \param *p_st_private     (L7session_jboss_private      私有数据)
 *
 */
FR_STATIC void __jboss_session_filter(char *p_data_in, int i_data_len, L7session_jboss_private *p_st_private)
{
    if(p_data_in == NULL || i_data_len < 5 || p_st_private == NULL)
        return;

    if(*(p_data_in + 4) == '\x15' || *(p_data_in + 4) == '\x1e' || *(p_data_in + 4) == '\x1f' )
    {
        p_st_private->i_session = 1;
    }

    return;
}

/*!
 * jboss req 的packet解析
 *
 * \param *p_st_conn           (Conntrack          连接信息)
 * \param *p_st_packet        (Apm_packet    数据包信息)
 * \param *p_st_hash_report    (Frhash_header      上报链表)
 * \param *p_st_session        (L7_session         私有数据)
 *
 * \return APM_L7_ANALYZE_SUCC:成功\n
 *         APM_L7_ANALYZE_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包不完整
 *
 */
FR_STATIC int __req_data_analysis(Conntrack *p_st_conn
                                 , Apm_packet *p_st_packet
                                 , Frhash_header *p_st_hash_report
                                 , L7_session *p_st_session)
{
    int i_ret = 0;
    L7session_jboss_private *p_st_private = NULL;
    L4_transaction *p_st_l4_trans = NULL;
    Frreport_data *p_st_report_data = NULL;
    unsigned long ul_tmp = 0;

    if(p_st_conn == NULL || p_st_packet == NULL
        || p_st_hash_report == NULL || p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_st_private = (L7session_jboss_private*)p_st_session->p_session_private;
    p_st_l4_trans = &(p_st_private->st_l4_trans);
    p_st_private->i_use_request = FR_YES;

    //第一个包  创建private 数据
    if(p_st_l4_trans->st_request_time_first_byte.tv_sec == 0
        && p_st_l4_trans->st_request_time_first_byte.tv_usec == 0)
    {
        //session 数据
        __jboss_session_filter(p_st_packet->p_payload, p_st_packet->ui_payload_len, p_st_private);
        if(p_st_private->i_session)
        {
            p_st_private->i_session = 0;

            i_ret = bytebuff_add(p_st_private->p_st_data, p_st_packet->p_payload, p_st_packet->ui_payload_len);
            if(i_ret == FR_FAIL)
                return APM_L7_ANALYZE_FAIL;

            i_ret = jboss_session_parse(p_st_private->p_st_data, p_st_private, FR_YES);
            if(i_ret == APM_L7_ANALYZE_FAIL)
                return APM_L7_ANALYZE_FAIL;

            if(i_ret == APM_L7_ANALYZE_SUCC)
            {
                //session 数据处理
                if(p_st_private->i_flag_data_type == FRLOGIN_START)
                {
                    p_st_private->st_login_timestamp.tv_sec = p_st_packet->st_timestamp.tv_sec;
                    p_st_private->st_login_timestamp.tv_usec = p_st_packet->st_timestamp.tv_usec;

                    fruuid(p_st_private->arr_session_id);
                    p_st_private->i_flag_data_type = 0;
                }

                if(__jboss_session_reset(p_st_private) == FR_FAIL)
                    return APM_L7_ANALYZE_FAIL;
                return APM_L7_ANALYZE_SET_REQ (APM_L7_ANALYZE_SUCC);
            }
        }
        // 判断是否是需要的数据包  如果不需要跳过数据
        __jboss_data_filter(p_st_packet->p_payload, p_st_packet->ui_payload_len, p_st_private);

        if(p_st_private->i_flag_report == 0)
        {
            if(p_st_private->i_data_len == 0)
            {
                if(p_st_packet->ui_payload_len < 4)
                    return APM_L7_ANALYZE_FAIL;

                p_st_private->i_data_len = pntohi(p_st_packet->p_payload);

                if((unsigned int)p_st_private->i_data_len > p_st_packet->ui_payload_len - 4)
                {
                    p_st_private->i_data_len -= (p_st_packet->ui_payload_len - 4);
                    return APM_L7_ANALYZE_TODO;
                }
                else
                {
                    p_st_private->i_data_len = 0;
                    return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);
                }
            }
            else
            {
                if((unsigned int)p_st_private->i_data_len > p_st_packet->ui_payload_len)
                {
                    p_st_private->i_data_len -= (p_st_packet->ui_payload_len);
                    return APM_L7_ANALYZE_TODO;
                }
                else
                {
                    p_st_private->i_data_len = 0;
                    return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);
                }
            }
        }

        p_st_private->p_st_body_data_req = frreport_body_new_l7(p_st_conn);
        if(p_st_private->p_st_body_data_req == NULL)
            return APM_L7_ANALYZE_FAIL;

        //st_request_time_first_byte
        p_st_l4_trans->st_request_time_first_byte.tv_sec = p_st_packet->st_timestamp.tv_sec;
        p_st_l4_trans->st_request_time_first_byte.tv_usec = p_st_packet->st_timestamp.tv_usec;

        //seq ++
        p_st_private->ul_seq = frct_seq_increase(p_st_conn);
    }
    //st_request_time
    p_st_l4_trans->st_request_time.tv_sec = p_st_packet->st_timestamp.tv_sec;
    p_st_l4_trans->st_request_time.tv_usec = p_st_packet->st_timestamp.tv_usec;

    /* 请求的字节数 */
    p_st_l4_trans->l_request_bytes += p_st_packet->ui_payload_len;

    i_ret = bytebuff_add(p_st_private->p_st_data, p_st_packet->p_payload, p_st_packet->ui_payload_len);
    if(i_ret == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;

    //如果skip长度有剩余  返回TODO
    if((p_st_private->p_st_data)->ui_skip_len)
        return APM_L7_ANALYZE_TODO;

    i_ret = jboss_content_parse(p_st_private->p_st_data, p_st_private->p_st_body_data_req, p_st_private, FR_YES);
    if(i_ret == APM_L7_ANALYZE_FAIL)
        return APM_L7_ANALYZE_FAIL;

    //数据上报
    if(i_ret == APM_L7_ANALYZE_SUCC)
    {
        if(p_st_private->i_flag_report)
        {
            i_ret = frreport_body_l7_add_connInfo(p_st_private->p_st_body_data_req, p_st_conn);
            if(i_ret == FR_FAIL)
                return APM_L7_ANALYZE_FAIL;
            //session
            //title
            if(__jboss_session_report(p_st_private->p_st_body_data_req, p_st_private) == FR_FAIL)
                goto ERROR;

            //response required
            if(frreport_body_l7_add_int(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_ISRESPREQUIRED, 1) == FR_FAIL)
                goto ERROR;

            //seq
            if(frreport_body_l7_add_ulong(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_ID, p_st_private->ul_seq) == FR_FAIL)
                goto ERROR;

            //first byte time
            if(frreport_body_l7_add_timeval(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_START_TIMESTAMP, &p_st_l4_trans->st_request_time_first_byte) == FR_FAIL)
                goto ERROR;

            //request end time
            if(frreport_body_l7_add_timeval(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_END_TIMESTAMP, &p_st_l4_trans->st_request_time) == FR_FAIL)
                goto ERROR;

            //send time us
            ul_tmp = frtime_diff(&p_st_l4_trans->st_request_time_first_byte, &p_st_l4_trans->st_request_time);
            if(frreport_body_l7_add_ulong(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_SEND_TIME_US, ul_tmp) == FR_FAIL)
                goto ERROR;

            //bytes
            if(frreport_body_l7_add_long(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_DATA_BYTES, p_st_l4_trans->l_request_bytes) == FR_FAIL)
                goto ERROR;

            if(p_st_private->is_message)
                p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_REQ);
            else
                p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_SUB);

            if(p_st_report_data == NULL)
                goto ERROR;

            p_st_private->p_lst_comm_tmp = FRREPORT_BODY_L7LIST_CLONE_COMM(p_st_private->p_st_body_data_req);
            if(p_st_private->p_lst_comm_tmp == NULL)
                goto ERROR;

            p_st_private->p_lst_req_tmp = FRREPORT_BODY_L7LIST_CLONE_REQ(p_st_private->p_st_body_data_req);
            if(p_st_private->p_lst_req_tmp == NULL)
                goto ERROR;

//            if(p_st_private->is_topic)
//            {
//                p_st_private->p_lst_mq_tmp = FRREPORT_BODY_L7LIST_CLONE_MQ(p_st_private->p_st_body_data_req);
//                if(p_st_private->p_lst_mq_tmp == NULL)
//                    goto ERROR;
//            }

            if(frreport_data_add_body(p_st_report_data, p_st_private->p_st_body_data_req) == FR_FAIL)
                goto ERROR;
            p_st_private->p_st_body_data_req = NULL;

            if(frreport_data_hash(p_st_hash_report, p_st_report_data) == FR_FAIL)
                goto ERROR;

        }
        else
        {
            if(__jboss_session_reset(p_st_private) == FR_FAIL)
                return APM_L7_ANALYZE_FAIL;
        }
    }

    if(i_ret == APM_L7_ANALYZE_SUCC)
        return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);

    return i_ret;

ERROR:
    if(p_st_report_data)
        frreport_data_free(&p_st_report_data);

    if(p_st_private->p_lst_comm_tmp)
        frreport_body_l7list_free(&p_st_private->p_lst_comm_tmp);

    if(p_st_private->p_lst_req_tmp)
        frreport_body_l7list_free(&p_st_private->p_lst_req_tmp);

    if(p_st_private->p_lst_mq_tmp)
        frreport_body_l7list_free(&p_st_private->p_lst_mq_tmp);

    return APM_L7_ANALYZE_FAIL;
}


/*!
 * jboss resp 的packet解析
 *
 * \param *p_st_conn           (Conntrack          连接信息)
 * \param *p_st_packet        (Apm_packet    数据包信息)
 * \param *p_st_hash_report    (Frhash_header      上报链表)
 * \param *p_st_session        (L7_session         私有数据)
 *
 * \return APM_L7_ANALYZE_SUCC:成功\n
 *         APM_L7_ANALYZE_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包不完整
 *
 */
FR_STATIC int __resp_data_analysis(Conntrack *p_st_conn
                                 , Apm_packet *p_st_packet
                                 , Frhash_header *p_st_hash_report
                                 , L7_session *p_st_session)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    L7session_jboss_private *p_st_private = NULL;
    L4_transaction *p_st_l4_trans = NULL;
    Frreport_data *p_st_report_data = NULL;
    unsigned long ul_tmp = 0;
    char arr_info[1024];

    if(p_st_conn == NULL || p_st_packet == NULL
        || p_st_hash_report == NULL || p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_st_private = (L7session_jboss_private*)p_st_session->p_session_private;
    p_st_l4_trans = &(p_st_private->st_l4_trans);

    p_st_private->i_use_request = FR_NO;

    if (p_st_l4_trans->st_response_time_first_byte.tv_sec == 0 &&
        p_st_l4_trans->st_response_time_first_byte.tv_usec == 0)
    {
        //session 数据
        __jboss_session_filter(p_st_packet->p_payload, p_st_packet->ui_payload_len, p_st_private);
        if(p_st_private->i_session)
        {
            p_st_private->i_session = 0;

            i_ret = bytebuff_add(p_st_private->p_st_data, p_st_packet->p_payload, p_st_packet->ui_payload_len);
            if(i_ret == FR_FAIL)
                return APM_L7_ANALYZE_FAIL;

            i_ret = jboss_session_parse(p_st_private->p_st_data, p_st_private, FR_YES);
            if(i_ret == APM_L7_ANALYZE_FAIL)
                return APM_L7_ANALYZE_FAIL;

            if(i_ret == APM_L7_ANALYZE_SUCC)
            {
                if (p_st_private->i_flag_data_type == FRLOGIN_SUCC)
                {
                    if (p_st_private->p_user_name != NULL && *p_st_private->p_user_name != '\0')
                        snprintf(arr_info, sizeof(arr_info), "%s login", p_st_private->p_user_name);
                    else
                        snprintf(arr_info, sizeof(arr_info), "login");

                    p_st_report_data = frreport_update_create(p_st_conn, APM_REPORT_UPDATE_LOGON, arr_info, &p_st_packet->st_timestamp);

                }
                else if (p_st_private->i_flag_data_type == FRLOGIN_FAIL)
                {
                    if (p_st_private->p_user_name != NULL && *p_st_private->p_user_name != '\0')
                        snprintf(arr_info, sizeof(arr_info), "%s login reject", p_st_private->p_user_name);
                    else
                        snprintf(arr_info, sizeof(arr_info), "login reject");

                    p_st_report_data = frreport_update_create(p_st_conn, APM_REPORT_UPDATE_LOGON_REJECT, arr_info, &p_st_packet->st_timestamp);

                }
                else if(p_st_private->i_flag_data_type == FRLOGOUT_END)
                {

                    if (p_st_private->p_user_name != NULL && *p_st_private->p_user_name != '\0')
                        snprintf(arr_info, sizeof(arr_info), "%s logout", p_st_private->p_user_name);
                    else
                        snprintf(arr_info, sizeof(arr_info), "logout");

                    p_st_report_data = frreport_update_create(p_st_conn, APM_REPORT_UPDATE_LOGOUT, arr_info, &p_st_packet->st_timestamp);

                }

                p_st_private->i_flag_data_type = 0;
                if (p_st_report_data)
                {
                    if(frreport_send(g_p_apm_context, &p_st_report_data) == FR_FAIL)
                    {
                        frreport_data_free(&p_st_report_data);
                        return APM_L7_ANALYZE_FAIL;
                    }
                }

                if(__jboss_session_reset(p_st_private) == FR_FAIL)
                    goto ERROR;

                return APM_L7_ANALYZE_SET_RESP (APM_L7_ANALYZE_SUCC);
            }
        }

        __jboss_data_filter(p_st_packet->p_payload, p_st_packet->ui_payload_len, p_st_private);

        //不上报数据处理
        if(p_st_private->i_flag_report == 0)
        {
            //p_st_private->i_data_len
            if(p_st_private->i_data_len == 0)
            {
                if(p_st_packet->ui_payload_len < 4)
                    return APM_L7_ANALYZE_FAIL;

                p_st_private->i_data_len = pntohi(p_st_packet->p_payload);

                if((unsigned int)p_st_private->i_data_len > p_st_packet->ui_payload_len - 4)
                {
                    p_st_private->i_data_len -= (p_st_packet->ui_payload_len - 4);
                    return APM_L7_ANALYZE_TODO;
                }
                else
                {
                    p_st_private->i_data_len = 0;
                    return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);
                }
            }
            else
            {
                if((unsigned int)p_st_private->i_data_len > p_st_packet->ui_payload_len)
                {
                    p_st_private->i_data_len -= (p_st_packet->ui_payload_len);
                    return APM_L7_ANALYZE_TODO;
                }
                else
                {
                    p_st_private->i_data_len = 0;
                    return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);
                }
            }

        }

        p_st_private->p_st_body_data_resp = frreport_body_new_l7(p_st_conn);
        if(p_st_private->p_st_body_data_resp == NULL)
            return APM_L7_ANALYZE_FAIL;

        //应答发起时间戳
        p_st_l4_trans->st_response_time_first_byte.tv_sec = p_st_packet->st_timestamp.tv_sec;
        p_st_l4_trans->st_response_time_first_byte.tv_usec = p_st_packet->st_timestamp.tv_usec;

        //首包时间
        if(p_st_l4_trans->st_request_time_first_byte.tv_sec != 0)
            p_st_l4_trans->ul_response_time_firstbyte_us = frtime_diff(&(p_st_l4_trans->st_request_time_first_byte), &(p_st_l4_trans->st_response_time_first_byte));
        else
            p_st_l4_trans->ul_response_time_firstbyte_us = 0;

    }

    //st_response_time
    p_st_l4_trans->st_response_time.tv_sec = p_st_packet->st_timestamp.tv_sec;
    p_st_l4_trans->st_response_time.tv_usec = p_st_packet->st_timestamp.tv_usec;
    /* 请求的字节数 */
    p_st_l4_trans->l_response_bytes += p_st_packet->ui_payload_len;

    //添加到bytebyff
    i_ret = bytebuff_add(p_st_private->p_st_data, p_st_packet->p_payload, p_st_packet->ui_payload_len);
    if(i_ret == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;

    //如果skip长度有剩余  返回TODO
    if((p_st_private->p_st_data)->ui_skip_len)
        return APM_L7_ANALYZE_TODO;

    i_ret = jboss_content_parse(p_st_private->p_st_data, p_st_private->p_st_body_data_resp, p_st_private, FR_YES);
    //数据上报
    if(i_ret == APM_L7_ANALYZE_SUCC)
    {
        if(p_st_private->ul_seq == 0 || p_st_private->p_lst_comm_tmp == NULL)
            p_st_private->ul_seq = frct_seq_increase(p_st_conn);

        //数据链表  设置为response
        if(p_st_private->p_lst_comm_tmp == NULL)
        {
            i_ret = frreport_body_l7_add_connInfo(p_st_private->p_st_body_data_resp, p_st_conn);
            if(i_ret == FR_FAIL)
                goto ERROR;

            if(frreport_body_l7_add_ulong(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_SERVER_TIME_US, 0) == FR_FAIL)
                goto ERROR;

            if(__jboss_session_report(p_st_private->p_st_body_data_resp, p_st_private) == FR_FAIL)
                goto ERROR;
        }
        else
        {
            //comm
            if(FRREPORT_BODY_L7LIST_SET_COMM(p_st_private->p_st_body_data_resp, &p_st_private->p_lst_comm_tmp) == FR_FAIL)
                goto ERROR;

            //把req数据链表添加到resp中
            if(FRREPORT_BODY_L7LIST_SET_REQ(p_st_private->p_st_body_data_resp, &p_st_private->p_lst_req_tmp) == FR_FAIL)
                goto ERROR;

            if(p_st_private->p_lst_mq_tmp)
            {
                if(FRREPORT_BODY_L7LIST_SET_MQ(p_st_private->p_st_body_data_resp, &p_st_private->p_lst_mq_tmp) == FR_FAIL)
                    goto ERROR;
            }

            ul_tmp = frtime_diff(&p_st_l4_trans->st_request_time, &p_st_l4_trans->st_response_time_first_byte);
            if(frreport_body_l7_add_ulong(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_SERVER_TIME_US, ul_tmp) == FR_FAIL)
                goto ERROR;

        }

        if(frreport_body_l7_add_int(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_CODE, 0) == FR_FAIL)
            goto ERROR;

        if(frreport_body_l7_add_timeval(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_START_TIMESTAMP, &p_st_l4_trans->st_response_time_first_byte) == FR_FAIL)
            goto ERROR;

        if(frreport_body_l7_add_timeval(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_END_TIMESTAMP, &p_st_l4_trans->st_response_time) == FR_FAIL)
            goto ERROR;

        ul_tmp = frtime_diff(&p_st_l4_trans->st_response_time_first_byte, &p_st_l4_trans->st_response_time);
        if(frreport_body_l7_add_ulong(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_DOWNLOAD_TIME_US, ul_tmp) == FR_FAIL)
            goto ERROR;

        if(frreport_body_l7_add_long(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_DATA_BYTES, p_st_l4_trans->l_response_bytes) == FR_FAIL)
            goto ERROR;

        if(p_st_private->is_message)
            p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_NOTIFY);
        else
            p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_RESP);

        if(p_st_report_data == NULL)
            goto ERROR;

        if(frreport_data_add_body(p_st_report_data, p_st_private->p_st_body_data_resp) == FR_FAIL)
            goto ERROR;
        p_st_private->p_st_body_data_resp = NULL;

        if(frreport_data_hash(p_st_hash_report, p_st_report_data) == FR_FAIL)
            goto ERROR;

        if(__jboss_session_reset(p_st_private) == FR_FAIL)
            goto ERROR;

        return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);
    }

    return i_ret;

ERROR:
    if(p_st_report_data)
        frreport_data_free(&p_st_report_data);

    return APM_L7_ANALYZE_FAIL;
}


/*!
 * jboss 解析
 *
 * \param *p_st_conn           (Conntrack          连接信息)
 * \param *p_st_packet        (Apm_packet    数据包信息)
 * \param *p_st_hash_report    (Frhash_header      上报链表)
 *
 * \return APM_L7_ANALYZE_SUCC:成功\n
 *         APM_L7_ANALYZE_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包不完整
 *
 */
int jboss_analysis(Conntrack *p_st_conn
                  , Apm_packet *p_st_packet
                  , Frhash_header *p_st_hash_report)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    L7_session *p_st_session = NULL;

    if(p_st_conn == NULL || p_st_packet == NULL
        || p_st_hash_report == NULL)
        return APM_L7_ANALYZE_FAIL;

    /* 到Conntrack中取得session信息 */
    p_st_session = frct_get_session(p_st_conn);
    if (p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    //fin syn 包  销毁私有数据
    if(p_st_packet->em_analyz_cmd == FRANALYZ_CMD_FIN || p_st_packet->em_analyz_cmd == FRANALYZ_CMD_SYN)
    {
        jboss_session_destroy((void *)(p_st_session->p_session_private));
        p_st_session->p_session_private = NULL;
        return APM_L7_ANALYZE_SUCC;
    }

    //p_session_private   分配内存
    if(p_st_session->p_session_private == NULL)
    {
        p_st_session->p_session_private = __jboss_private_create();
        //内存分配失败
        if(p_st_session->p_session_private == NULL)
            return APM_L7_ANALYZE_FAIL;
    }

    //request
    if(p_st_packet->i_direction == FR_DIRECT_CLIENT2SRV)
    {
        i_ret = __req_data_analysis(p_st_conn,p_st_packet,p_st_hash_report,p_st_session);
        if(i_ret == APM_L7_ANALYZE_FAIL)
            goto ERROR;

        return i_ret;
    }
    else//response
    {
        i_ret = __resp_data_analysis(p_st_conn,p_st_packet,p_st_hash_report, p_st_session);
        if (i_ret == APM_L7_ANALYZE_FAIL)
            goto ERROR;

        return i_ret;
    }

ERROR:
    jboss_session_destroy(p_st_session->p_session_private);
    p_st_session->p_session_private = NULL;

    return APM_L7_ANALYZE_FAIL;}


/*!
 * jboss 私有信息销毁
 *
 * \param *p_private_session    (jboss的私有session数据)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 */
int jboss_session_destroy(void *p_private_session)
{
    L7session_jboss_private *p_st_private = (L7session_jboss_private*)p_private_session;

    if(p_st_private)
    {
        if(p_st_private->p_st_body_data_req)
            frreport_body_free(&p_st_private->p_st_body_data_req);

        if(p_st_private->p_st_body_data_resp)
            frreport_body_free(&p_st_private->p_st_body_data_resp);

        if(p_st_private->p_lst_comm_tmp)
            frreport_body_l7list_free(&p_st_private->p_lst_comm_tmp);

        if(p_st_private->p_lst_req_tmp)
            frreport_body_l7list_free(&p_st_private->p_lst_req_tmp);

        if(p_st_private->p_lst_mq_tmp)
            frreport_body_l7list_free(&p_st_private->p_lst_mq_tmp);

        if(p_st_private->p_st_data)
            bytebuff_free(&p_st_private->p_st_data);

        if(p_st_private->p_user_name)
            frfree(p_st_private->p_user_name);

        if(p_st_private->p_title)
            frfree(p_st_private->p_title);

        frfree(p_st_private);
    }
    return FR_SUCC;
}




